package com.xhwl.centiotdata.handler.pedestrian.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xhwl.centiotdata.handler.pedestrian.PedestrianIntegrationFactory;
import com.xhwl.centiotdata.handler.pedestrian.PedestrianIntegrationHandler;
import com.xhwl.centiotdata.pojo.constant.LiFangConstant;
import com.xhwl.centiotdata.pojo.dto.lifang.PedestrianRecordLiFangDTO;
import com.xhwl.centiotdata.pojo.dto.lifang.UserLiFangDTO;
import com.xhwl.centiotdata.pojo.dto.pedestrian.PedestrianIntegrationConfigDTO;
import com.xhwl.centiotdata.service.cent.*;
import com.xhwl.centiotdata.service.impl.DeviceServiceImpl;
import com.xhwl.centiotdata.service.integrateconfig.IntegrationConfig;
import com.xhwl.centiotdata.suppliersystem.lifang.PedestrianLiFangHandler;
import com.xhwl.centiotdata.utils.Base64Utils;
import com.xhwl.common.dto.auth.AuthDeviceDTO;
import com.xhwl.common.dto.auth.PedestrianAuthDTO;
import com.xhwl.common.dto.cent.device.DeviceDTO;
import com.xhwl.common.dto.cent.pedes.OpenDoorRecordDTO;
import com.xhwl.common.dto.cent.sdata.GroupDTO;
import com.xhwl.common.enums.*;
import com.xhwl.common.enums.pedestrian.DoorActionEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.auth.AuthAccountMapping;
import com.xhwl.common.pojo.cent.device.Device;
import com.xhwl.common.pojo.cent.device.DeviceProjSupplierCategory;
import com.xhwl.common.pojo.cent.sdata.Account;
import com.xhwl.common.pojo.cent.sdata.Organization;
import com.xhwl.common.query.cent.auth.AuthDeviceQuery;
import com.xhwl.common.query.cent.device.DeviceGroupQuery;
import com.xhwl.common.query.cent.sdata.AccountQuery;
import com.xhwl.common.query.cent.sdata.GroupQuery;
import com.xhwl.common.query.cent.sdata.OrganizationQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import sun.misc.BASE64Encoder;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * @Author: yanyixiong
 * @Description:
 * @Date: create in 10:24 2022/7/12
 */
@Slf4j
@Service
public class PedestrianIntegrationLiFangHandler extends PedestrianIntegrationHandler {

    @Autowired
    private IPedestrianCentService pedestrianCentService;
    @Autowired
    private PedestrianLiFangHandler pedestrianLiFangHandler;
    @Autowired
    private IAuthAccountCentService authAccountCentService;
    @Autowired
    private IAccountCentService accountCentService;
    @Autowired
    private DeviceServiceImpl deviceService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IProjectCentService iProjectCentService;
    @Autowired
    private IDeviceCentService deviceCentService;

    @Override
    public void afterPropertiesSet() throws Exception {
        PedestrianIntegrationFactory.register(ProductEnum.LIFANG_OCS.getId(), this);
    }

    @Override
    public void pullRecord(PedestrianIntegrationConfigDTO configDTO, Integer intervalDays, Date date) {
        // 拉取数据
        List<PedestrianRecordLiFangDTO> recordLiFangList = pedestrianLiFangHandler.pullRecord(configDTO);
        if (CollectionUtils.isEmpty(recordLiFangList)) {
            return;
        }
        // 转换数据
        List<OpenDoorRecordDTO> openDoorRecordDTOList = this.handleRecord(configDTO, recordLiFangList);
        // 存储业务中台
        pedestrianCentService.saveBatch(openDoorRecordDTOList);
    }

    @Override
    public ResultJson openDoor(PedestrianIntegrationConfigDTO pedestrianIntegrationConfigDTO, DeviceDTO deviceDTO, DoorActionEnum doorAction) {
        return pedestrianLiFangHandler.remoteOpenDoor(pedestrianIntegrationConfigDTO, deviceDTO, doorAction);
    }

    @Override
    public ResultJson createAuth(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        AuthAccountMapping accountMapping = this.createUser(configDTO, pedestrianAuthDTO);
        String openId = accountMapping.getOpenId();
        authAccountCentService.save(configDTO.getProjectId(), pedestrianAuthDTO.getSourceId(),openId,null,configDTO.getProductId());
        pedestrianAuthDTO.setUserOpenId(openId);
        pedestrianAuthDTO.setCardNumber(createCard());
        pedestrianLiFangHandler.sendCard(configDTO,pedestrianAuthDTO);
        // 授权
        if (!StringUtils.isEmpty(pedestrianAuthDTO.getFaceUrl())){
            pedestrianAuthDTO.setImageBase(Base64Utils.imageUrlToBase64(pedestrianAuthDTO.getFaceUrl()));
            pedestrianLiFangHandler.addPhoto(configDTO,pedestrianAuthDTO);
        }
        pedestrianLiFangHandler.createAuth(configDTO,pedestrianAuthDTO);
        return ResultJson.success();
    }

    @Override
    public ResultJson updateAuth(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        if (!StringUtils.isEmpty(pedestrianAuthDTO.getFaceUrl())){
            pedestrianAuthDTO.setImageBase(Base64Utils.imageUrlToBase64(pedestrianAuthDTO.getFaceUrl()));
            pedestrianLiFangHandler.addPhoto(configDTO,pedestrianAuthDTO);
        }
        //第三方授权门禁
        List<String> deleteDoorIds = pedestrianLiFangHandler.findAuth(configDTO,pedestrianAuthDTO);
        //要修改的授权门禁
        List<Integer> updateList = new ArrayList<>();
        AuthDeviceQuery authDeviceQuery = new AuthDeviceQuery();
        if (null != pedestrianAuthDTO.getId()){
            //查询用户是否还存在用户组
            GroupQuery groupQuery  = new GroupQuery();
            groupQuery.setId(pedestrianAuthDTO.getId());
            List<GroupDTO> list = accountCentService.getList(groupQuery);
            if(CollectionUtils.isEmpty(list)){
                authDeviceQuery.setSourceId(pedestrianAuthDTO.getSourceId());
            }else {
                if(CollectionUtils.isEmpty(list.get(0).getAccountIds())){
                    authDeviceQuery.setSourceId(pedestrianAuthDTO.getSourceId());
                }else {
                    List<Integer> ids = list.get(0).getAccountIds().stream().filter(id ->  pedestrianAuthDTO.getSourceId().equals(id)).collect(toList());
                    if (CollectionUtils.isEmpty(ids)){
                        authDeviceQuery.setSourceId(pedestrianAuthDTO.getSourceId());
                    }else {
                        authDeviceQuery.setSourceId(list.get(0).getId());
                    }
                }
            }
        }else {
            authDeviceQuery.setSourceId(pedestrianAuthDTO.getSourceId());
        }
        authDeviceQuery.setProjectId(configDTO.getProjectId());
        authDeviceQuery.setCategoryId(CategoryEnum.DOOR.getId());
        List<AuthDeviceDTO> authDeviceDTOS = authAccountCentService.listObjectWithInfo(authDeviceQuery);
        log.info("获取设备信息，入参{}，返回{}", JSONObject.toJSONString(authDeviceQuery),CollectionUtils.isEmpty(authDeviceDTOS)?null:JSON.toJSONString(authDeviceDTOS));
        if (CollectionUtils.isEmpty(authDeviceDTOS)){
            log.info("获取设备信息为空,删除授权");
            pedestrianAuthDTO.setDeletedThirdDeviceIdList(deleteDoorIds);
            if (!CollectionUtils.isEmpty(pedestrianAuthDTO.getDeletedThirdDeviceIdList())){
                log.info("Li Fang 删除授权");
                this.deleteAuth(configDTO,pedestrianAuthDTO);
            }
            return ResultJson.success();
        }
        //要授权的设备第三方id
        List<String> list = new ArrayList<>();
        //获取授权的设备
        List<AuthDeviceDTO> devices = authDeviceDTOS.stream().filter(authDeviceDTO -> authDeviceDTO.getRelevanceType().equals(AuthRelevanceTypeEnum.DEVICE.type)).collect(toList());
        if (!CollectionUtils.isEmpty(devices)){
            updateList.addAll(devices.stream().map(AuthDeviceDTO::getRelevanceId).collect(toList()));
        }
        //获取授权的设备组
        List<AuthDeviceDTO>  deviceGroups = authDeviceDTOS.stream().filter(authDeviceDTO -> authDeviceDTO.getRelevanceType().equals(AuthRelevanceTypeEnum.DEVICE_GROUP.type)).collect(toList());
        if (!CollectionUtils.isEmpty(deviceGroups)){
            List<Integer>  groups = deviceGroups.stream().map(AuthDeviceDTO::getRelevanceId).collect(toList());
            groups.forEach(id->{
                DeviceGroupQuery deviceGroupQuery = new DeviceGroupQuery();
                deviceGroupQuery.setId(id);
                deviceGroupQuery.setSize(500L);
                deviceGroupQuery.setCurrent(1L);
                Page<Device> devicePage = deviceCentService.queryRelation(deviceGroupQuery);
                if (null!=devicePage && !CollectionUtils.isEmpty(devicePage.getRecords())){
                    updateList.addAll(devicePage.getRecords().stream().map(Device::getId).collect(Collectors.toList()));
                }
            });
        }

        if (!CollectionUtils.isEmpty(updateList)){
            log.info("查找的设备id列表：{}",JSON.toJSONString(updateList));
            List<DeviceDTO> deviceDTOS = deviceService.findDevice(null, null, CategoryEnum.DOOR.getId(), updateList);
            if (!CollectionUtils.isEmpty(deviceDTOS)) {
                list.addAll(deviceDTOS.stream().map(DeviceDTO::getThirdDeviceId).collect(toList()));
            }
        }
        //比对重新授权的门禁与已经授权过的门禁，删除需要解除的，重新授权
        if (!CollectionUtils.isEmpty(deleteDoorIds)){
            //已经授权过的设备
             if (!CollectionUtils.isEmpty(list) && !CollectionUtils.isEmpty(deleteDoorIds) ){
                log.info("Li Fang 已授权：{}，需授权：{}",JSON.toJSONString(deleteDoorIds),list);
                List<String> deleteDevices = deleteDoorIds.stream().filter(id-> !list.contains(id)).collect(toList());
                log.info("删除授权的门禁：{}",JSON.toJSONString(deleteDevices));
                pedestrianAuthDTO.setDeletedThirdDeviceIdList(deleteDevices);
            }else {
                log.info("Li Fang 无需授权");
                return ResultJson.success();
            }
            if (!CollectionUtils.isEmpty(pedestrianAuthDTO.getDeletedThirdDeviceIdList())){
                log.info("Li Fang 删除授权");
                this.deleteAuth(configDTO,pedestrianAuthDTO);
            }
        }
        if (!CollectionUtils.isEmpty(list)) {
            pedestrianAuthDTO.setAddedThirdDeviceIdList(list);
            log.info("Li Fang 重新授权");
            pedestrianLiFangHandler.createAuth(configDTO,pedestrianAuthDTO);
        }

        return ResultJson.success();
    }

    @Override
    public ResultJson deleteAuth(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO) {
        if(CollectionUtils.isEmpty(pedestrianAuthDTO.getDeletedThirdDeviceIdList())){
            List<String> deleteDoorIds = pedestrianLiFangHandler.findAuth(configDTO,pedestrianAuthDTO);
            if (!CollectionUtils.isEmpty(deleteDoorIds)){
                pedestrianAuthDTO.setDeletedThirdDeviceIdList(deleteDoorIds);
            }else {
                log.info("无可删除门禁设备，直接返回");
                return  ResultJson.success();
            }
        }
        pedestrianLiFangHandler.deleteAuth(configDTO, pedestrianAuthDTO);
        return ResultJson.success();
    }

    private List<OpenDoorRecordDTO> handleRecord(PedestrianIntegrationConfigDTO configDTO, List<PedestrianRecordLiFangDTO> recordLiFangList) {
//        List<AuthAccountMapping> authAccountMappings = authAccountCentService.listByOpenCode(recordLiFangList.stream().map(PedestrianRecordLiFangDTO::getEmployeeSysNo).collect(Collectors.toList()));
//        Map<String,String> codeIdMap = new HashMap<>();
//        authAccountMappings.forEach(authAccountMapping -> {
//            codeIdMap.put(authAccountMapping.getOpenCode(),authAccountMapping.getOpenId());
//        });
        return recordLiFangList.stream()
                .map(recordLiFangDTO -> {
                    return OpenDoorRecordDTO.builder()
                            .projectId(configDTO.getProjectId())
                            .openUserId(recordLiFangDTO.getEmployeeSysNo())
                            .openDeviceId(String.valueOf(recordLiFangDTO.getDoorId()))
                            .sourceType(this.handleRecordSourceType(recordLiFangDTO))
                            .arrivalTime(recordLiFangDTO.getEventDate())
                            .pictureUrl(handleUrl(configDTO,recordLiFangDTO.getEmployeePhoto()))
                            .deviceName(recordLiFangDTO.getDoorName())
                            .state((short)1)
                            .type(this.handleRecordType(recordLiFangDTO.getCardType()))
                            .direction(this.handleDirection(recordLiFangDTO.getTypename()))
                            .approach(AccessApproachEnum.OFF_LINE.getId())
                            .userName(recordLiFangDTO.getEmployeeName()).build();
                }).collect(toList());
    }

    private Short handleDirection(String typename){
        switch (typename) {
            case LiFangConstant.RECORD_IN_SUCCESS:
                return DirectionEnum.IN.getId();
            case LiFangConstant.RECORD_OUT_SUCCESS:
                return DirectionEnum.OUT.getId();
            default:
                return DirectionEnum.UNKNOWN.getId();
        }
    }

    private Short handleRecordType(Integer openType) {
        switch (openType) {
            case 3:
                return AccessTypeEnum.IC_CARD.getId();
            case 6://非法卡
                return AccessTypeEnum.OTHER.getId();
            default:
                return AccessTypeEnum.OTHER.getId();
        }
    }

    private Integer handleRecordSourceType(PedestrianRecordLiFangDTO recordLiFangDTO) {
        return SourceTypeEnum.USER.type;
    }

    private Short handleRecordState(String recordType) {
        switch (recordType) {
            case LiFangConstant.RECORD_IN_SUCCESS:
            case LiFangConstant.RECORD_OUT_SUCCESS:
                return (short)1;
            default:
                return (short)0;
        }
    }
    private AuthAccountMapping createUser(PedestrianIntegrationConfigDTO configDTO, PedestrianAuthDTO pedestrianAuthDTO){
        Integer accountId = pedestrianAuthDTO.getSourceId();
        AccountQuery accountQuery = new AccountQuery();
        accountQuery.setId(accountId);
        Account account = accountCentService.getAccount(null, accountQuery);
        if(account == null){
            throw new BusinessException("不存在该人员！");
        }
        //集成配置获取部门
        List<DeviceProjSupplierCategory> configDTOList = IntegrationConfig.integrationConfigList.stream()
                .filter(configDTO2 -> configDTO.getProjectId().equals(configDTO2.getProjectId()) && CategoryEnum.DOOR.getId().equals(configDTO2.getProdCategoryId()))
                .collect(Collectors.toList());
        Integer depart = configDTOList.get(0).getProperties().getInteger("userDepartId");
        UserLiFangDTO userLiFangDTO = UserLiFangDTO.builder()
                .name(account.getName())
                .deptId(depart)
                .userType("A")
                .phone(account.getPhone())
                .sex(account.getSex() == null || account.getSex() == 0 ? 2 : 1)
                .build();
        AuthAccountMapping authAccountMapping = new AuthAccountMapping();
        authAccountMapping.setOpenId(pedestrianLiFangHandler.createUser(configDTO, userLiFangDTO));
        return authAccountMapping;
    }

    private String handleUrl(PedestrianIntegrationConfigDTO configDTO, String url){
        if(!StringUtils.isEmpty(url)){
            return configDTO.getIpAndPort()+"/"+LiFangConstant.PROJECT+"/"+url;
        }
        return url;
    }
    private String createCard(){
        int machineId = 1;
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        if(hashCodeV < 0) {
            hashCodeV = - hashCodeV;
        }
        return machineId + String.format("%015d",hashCodeV);
    }
}
